# table_model.py
import numpy as np
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QStyledItemDelegate, QSpinBox


class ChannelDelegate(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = QSpinBox(parent)
        editor.setFrame(False)
        editor.setMinimum(1)
        editor.setMaximum(12)
        return editor

    def setEditorData(self, editor, index):
        text = index.model().data(index, Qt.ItemDataRole.EditRole)
        try:
            value = int(text.split(' ')[1]);
            editor.setValue(value)
        except (ValueError, IndexError):
            editor.setValue(1)

    def setModelData(self, editor, model, index):
        value = editor.value();
        model.setData(index, f"通道 {value}", Qt.ItemDataRole.EditRole)


class CalibrationDataModel:
    """
    一个专门用于管理标定数据的模型类。
    它处理所有的数据操作逻辑，使UI代码更简洁。
    增加了对(温度, 通道)组合的唯一性约束。
    """

    def __init__(self):
        self.data = []  # 存储标定数据的列表

    def _is_duplicate(self, temp: float, channel_index: int, is_single_mode: bool, ignore_row: int = -1) -> bool:
        """
        内部方法，检查是否存在重复的(温度, 通道)数据点。

        Args:
            temp (float): 要检查的温度。
            channel_index (int): 要检查的通道索引。
            is_single_mode (bool): 是否为单通道模式。
            ignore_row (int): 检查时要忽略的行索引（用于更新操作）。

        Returns:
            bool: 如果存在重复则返回True，否则返回False。
        """
        for i, point in enumerate(self.data):
            if i == ignore_row:
                continue

            # 使用 np.isclose 来比较浮点数，避免精度问题
            is_temp_match = np.isclose(point['temp'], temp)

            if is_single_mode:
                if is_temp_match and point.get('channel') == channel_index:
                    return True
            else:  # 12通道模式下，温度是唯一标识
                if is_temp_match:
                    return True
        return False

    def add_point(self, point_data: dict):
        """
        添加一个新的数据点，会先检查是否存在重复。
        Returns:
            bool: 添加成功返回True，因重复而失败返回False。
        """
        temp = point_data['temp']
        is_single = 'voltages' not in point_data

        if is_single:
            channel = point_data.get('channel', 0)
            if self._is_duplicate(temp, channel, is_single_mode=True):
                return False  # 存在重复
        else:  # 12通道模式
            if self._is_duplicate(temp, -1, is_single_mode=False):
                return False  # 存在重复

        self.data.append(point_data)
        return True

    def remove_row(self, row_index: int):
        """删除指定行的数据。"""
        if 0 <= row_index < len(self.data):
            self.data.pop(row_index)
            return True
        return False

    def update_value(self, row: int, col: int, new_value: float, is_single_mode: bool):
        """
        更新指定单元格的数据，会先检查温度修改是否导致重复。
        Returns:
            bool: 更新成功返回True，因重复而失败返回False。
        """
        if row >= len(self.data):
            return False

        # 如果修改的不是温度列，直接更新即可
        if col != 0:
            if is_single_mode:
                if col == 2: self.data[row]['voltage'] = new_value
            else:
                ch_index = col - 1
                if 'voltages' in self.data[row] and 0 <= ch_index < 12:
                    self.data[row]['voltages'][ch_index] = new_value
            return True

        # 如果修改的是温度列，需要检查重复
        channel = self.data[row].get('channel', 0) if is_single_mode else -1
        if self._is_duplicate(new_value, channel, is_single_mode, ignore_row=row):
            return False  # 修改会导致重复

        self.data[row]['temp'] = new_value
        return True

    def get_data_for_fit(self, is_single_mode: bool, channel_index: int = 0):
        """
        根据模式和通道，筛选并返回用于拟合的 x (温度) 和 y (电压) 数组。
        """
        # 为了保证拟合的顺序正确，先对数据按温度排序
        sorted_data = sorted(self.data, key=lambda p: p['temp'])

        if is_single_mode:
            channel_specific_data = [p for p in sorted_data if p.get('channel') == channel_index]
            if len(channel_specific_data) < 2:
                return None, None
            x_temps = [p['temp'] for p in channel_specific_data]
            y_volts = [p['voltage'] for p in channel_specific_data]
            return x_temps, y_volts
        else:  # 12路模式
            if len(sorted_data) < 2:
                return None, None
            x_temps = [p['temp'] for p in sorted_data]
            y_volts = [p['voltages'][channel_index] for p in sorted_data]
            return x_temps, y_volts

    def get_reference_voltage(self, reference_point: dict, is_single_mode: bool, channel_index: int = 0):
        """获取指定基准点和通道的参考电压。"""
        if not reference_point:
            return None
        if is_single_mode:
            if reference_point.get('channel') != channel_index:
                # 在单通道模式下，如果选择的基准点不属于当前通道，视为无效
                return None
            return reference_point.get('voltage')
        else:
            return reference_point.get('voltages')[channel_index]

    def clear(self):
        """清空所有数据。"""
        self.data.clear()

    def __len__(self):
        return len(self.data)